package com.example.backend.service;

import com.example.backend.domain.entity.*;
import com.example.backend.domain.enums.CommentType;
import com.example.backend.dto.SendNotificationRequest;
import com.example.backend.repository.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 工单协作服务
 * 提供@用户、内部讨论、关注、转发、批量操作等功能
 */
@Service
@Transactional
public class TicketCollaborationService {

    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private TicketFollowRepository ticketFollowRepository;

    @Autowired
    private TicketForwardRepository ticketForwardRepository;

    @Autowired
    private BatchOperationRepository batchOperationRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private TicketRepository ticketRepository;

    @Autowired
    private NotificationService notificationService;

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final Pattern mentionPattern = Pattern.compile("@(\\w+)");

    // ==================== @用户功能 ====================

    /**
     * 创建带@用户的评论
     */
    public Comment createCommentWithMentions(Ticket ticket, User author, String content, 
                                           CommentType commentType, Boolean isInternal, Comment parent) {
        try {
            // 解析@用户
            List<Long> mentionedUserIds = extractMentionedUsers(content);
            
            Comment comment = Comment.builder()
                    .ticket(ticket)
                    .author(author)
                    .content(content)
                    .commentType(commentType)
                    .isInternal(isInternal != null ? isInternal : false)
                    .parent(parent)
                    .mentionedUsers(mentionedUserIds.isEmpty() ? null : 
                        objectMapper.writeValueAsString(mentionedUserIds))
                    .build();
            
            Comment savedComment = commentRepository.save(comment);
            
            // 发送@通知
            if (!mentionedUserIds.isEmpty()) {
                sendMentionNotifications(savedComment, mentionedUserIds);
            }
            
            return savedComment;
        } catch (Exception e) {
            throw new RuntimeException("创建评论失败: " + e.getMessage(), e);
        }
    }

    /**
     * 解析评论中的@用户
     */
    private List<Long> extractMentionedUsers(String content) {
        List<Long> mentionedUserIds = new ArrayList<>();
        Matcher matcher = mentionPattern.matcher(content);
        
        while (matcher.find()) {
            String username = matcher.group(1);
            Optional<User> user = userRepository.findByUsername(username);
            if (user.isPresent()) {
                mentionedUserIds.add(user.get().getId());
            }
        }
        
        return mentionedUserIds.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 发送@通知
     */
    private void sendMentionNotifications(Comment comment, List<Long> mentionedUserIds) {
        for (Long userId : mentionedUserIds) {
            try {
                SendNotificationRequest request = new SendNotificationRequest();
                request.setUserId(userId);
                request.setTitle("工单评论中提到了您");
                request.setContent(String.format("在工单 #%s 的评论中提到了您", comment.getTicket().getTicketNumber()));
                request.setType(com.example.backend.domain.enums.NotificationType.COMMENT);
                request.setChannel(com.example.backend.domain.enums.NotificationChannel.IN_APP);
                request.setActionUrl("/tickets/" + comment.getTicket().getId());
                
                notificationService.createNotification(request);
            } catch (Exception e) {
                // 记录日志但不影响主流程
                System.err.println("发送@通知失败: " + e.getMessage());
            }
        }
    }

    /**
     * 获取评论中@的用户列表
     */
    public List<User> getMentionedUsers(Comment comment) {
        if (comment.getMentionedUsers() == null) {
            return Collections.emptyList();
        }
        
        try {
            List<Long> userIds = objectMapper.readValue(comment.getMentionedUsers(), 
                new TypeReference<List<Long>>() {});
            return userRepository.findAllById(userIds);
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }

    // ==================== 内部讨论功能 ====================

    /**
     * 创建内部讨论评论
     */
    public Comment createDiscussionComment(Ticket ticket, User author, String content, 
                                         String discussionType, Boolean isUrgent) {
        Comment comment = Comment.builder()
                .ticket(ticket)
                .author(author)
                .content(content)
                .commentType(CommentType.INTERNAL)
                .isInternal(true)
                .isDiscussion(true)
                .discussionType(discussionType)
                .isUrgent(isUrgent != null ? isUrgent : false)
                .build();
        
        Comment savedComment = commentRepository.save(comment);
        
        // 发送内部讨论通知
        sendDiscussionNotification(savedComment);
        
        return savedComment;
    }

    /**
     * 发送内部讨论通知
     */
    private void sendDiscussionNotification(Comment comment) {
        // 通知工单相关人员
        List<Long> notifyUserIds = getTicketStakeholders(comment.getTicket().getId());
        
        for (Long userId : notifyUserIds) {
            if (!userId.equals(comment.getAuthor().getId())) {
                try {
                    String title = comment.getIsUrgent() ? 
                        "🚨 紧急内部讨论" : "💬 内部讨论";
                    String message = String.format("工单 #%s 有新的内部讨论", 
                        comment.getTicket().getTicketNumber());
                    
                    SendNotificationRequest request = new SendNotificationRequest();
                    request.setUserId(userId);
                    request.setTitle(title);
                    request.setContent(message);
                    request.setType(com.example.backend.domain.enums.NotificationType.COMMENT);
                    request.setChannel(com.example.backend.domain.enums.NotificationChannel.IN_APP);
                    request.setActionUrl("/tickets/" + comment.getTicket().getId());
                    
                    notificationService.createNotification(request);
                } catch (Exception e) {
                    System.err.println("发送内部讨论通知失败: " + e.getMessage());
                }
            }
        }
    }

    /**
     * 获取工单相关人员ID列表
     */
    private List<Long> getTicketStakeholders(Long ticketId) {
        Optional<Ticket> ticketOpt = ticketRepository.findById(ticketId);
        if (ticketOpt.isEmpty()) {
            return Collections.emptyList();
        }
        
        Ticket ticket = ticketOpt.get();
        Set<Long> stakeholderIds = new HashSet<>();
        
        if (ticket.getCustomer() != null) {
            stakeholderIds.add(ticket.getCustomer().getId());
        }
        if (ticket.getAssignedTo() != null) {
            stakeholderIds.add(ticket.getAssignedTo().getId());
        }
        if (ticket.getCreatedBy() != null) {
            stakeholderIds.add(ticket.getCreatedBy().getId());
        }
        
        // 添加关注用户
        List<TicketFollow> follows = ticketFollowRepository.findByTicketIdAndNotificationEnabledTrue(ticketId);
        for (TicketFollow follow : follows) {
            stakeholderIds.add(follow.getUser().getId());
        }
        
        return new ArrayList<>(stakeholderIds);
    }

    /**
     * 获取工单的内部讨论
     */
    public List<Comment> getTicketDiscussions(Long ticketId) {
        return commentRepository.findByTicketIdAndIsInternalTrueOrderByCreatedAtAsc(ticketId);
    }

    // ==================== 关注/收藏功能 ====================

    /**
     * 关注工单
     */
    public TicketFollow followTicket(Long ticketId, Long userId, String followType, 
                                   Boolean notificationEnabled, List<String> notificationTypes) {
        try {
            // 检查是否已关注
            Optional<TicketFollow> existingFollow = ticketFollowRepository.findByTicketIdAndUserId(ticketId, userId);
            if (existingFollow.isPresent()) {
                return existingFollow.get();
            }
            
            Optional<Ticket> ticketOpt = ticketRepository.findById(ticketId);
            Optional<User> userOpt = userRepository.findById(userId);
            
            if (ticketOpt.isEmpty() || userOpt.isEmpty()) {
                throw new RuntimeException("工单或用户不存在");
            }
            
            TicketFollow follow = TicketFollow.builder()
                    .ticket(ticketOpt.get())
                    .user(userOpt.get())
                    .followType(followType)
                    .notificationEnabled(notificationEnabled != null ? notificationEnabled : true)
                    .notificationTypes(notificationTypes != null ? 
                        objectMapper.writeValueAsString(notificationTypes) : null)
                    .build();
            
            return ticketFollowRepository.save(follow);
        } catch (Exception e) {
            throw new RuntimeException("关注工单失败: " + e.getMessage(), e);
        }
    }

    /**
     * 取消关注工单
     */
    public void unfollowTicket(Long ticketId, Long userId) {
        ticketFollowRepository.deleteByTicketIdAndUserId(ticketId, userId);
    }

    /**
     * 检查用户是否关注了工单
     */
    public boolean isFollowingTicket(Long ticketId, Long userId) {
        return ticketFollowRepository.findByTicketIdAndUserId(ticketId, userId).isPresent();
    }

    /**
     * 获取用户关注的工单
     */
    public List<TicketFollow> getUserFollowedTickets(Long userId) {
        return ticketFollowRepository.findByUserIdOrderByCreatedAtDesc(userId, 
            org.springframework.data.domain.Pageable.unpaged()).getContent();
    }

    /**
     * 获取工单的关注用户
     */
    public List<TicketFollow> getTicketFollowers(Long ticketId) {
        return ticketFollowRepository.findByTicketIdOrderByCreatedAtAsc(ticketId);
    }

    // ==================== 工单转发功能 ====================

    /**
     * 转发工单
     */
    public TicketForward forwardTicket(Long ticketId, Long fromUserId, Long toUserId, 
                                     String forwardType, String reason, String priority, 
                                     Instant dueDate) {
        Optional<Ticket> ticketOpt = ticketRepository.findById(ticketId);
        Optional<User> fromUserOpt = userRepository.findById(fromUserId);
        Optional<User> toUserOpt = userRepository.findById(toUserId);
        
        if (ticketOpt.isEmpty() || fromUserOpt.isEmpty() || toUserOpt.isEmpty()) {
            throw new RuntimeException("工单或用户不存在");
        }
        
        TicketForward forward = TicketForward.builder()
                .ticket(ticketOpt.get())
                .fromUser(fromUserOpt.get())
                .toUser(toUserOpt.get())
                .forwardType(forwardType)
                .reason(reason)
                .priority(priority)
                .dueDate(dueDate)
                .build();
        
        TicketForward savedForward = ticketForwardRepository.save(forward);
        
        // 发送转发通知
        sendForwardNotification(savedForward);
        
        return savedForward;
    }

    /**
     * 发送转发通知
     */
    private void sendForwardNotification(TicketForward forward) {
        try {
            String title = "工单转发通知";
            String message = String.format("工单 #%s 已转发给您", 
                forward.getTicket().getTicketNumber());
            
            SendNotificationRequest request = new SendNotificationRequest();
            request.setUserId(forward.getToUser().getId());
            request.setTitle(title);
            request.setContent(message);
            request.setType(com.example.backend.domain.enums.NotificationType.TICKET);
            request.setChannel(com.example.backend.domain.enums.NotificationChannel.IN_APP);
            request.setActionUrl("/tickets/" + forward.getTicket().getId());
            
            notificationService.createNotification(request);
        } catch (Exception e) {
            System.err.println("发送转发通知失败: " + e.getMessage());
        }
    }

    /**
     * 响应转发
     */
    public TicketForward respondToForward(Long forwardId, String status, String responseMessage) {
        Optional<TicketForward> forwardOpt = ticketForwardRepository.findById(forwardId);
        if (forwardOpt.isEmpty()) {
            throw new RuntimeException("转发记录不存在");
        }
        
        TicketForward forward = forwardOpt.get();
        forward.setStatus(status);
        forward.setResponseMessage(responseMessage);
        forward.setRespondedAt(Instant.now());
        
        return ticketForwardRepository.save(forward);
    }

    /**
     * 获取用户的转发记录
     */
    public List<TicketForward> getUserForwards(Long userId, String status) {
        if (status != null) {
            return ticketForwardRepository.findByToUserIdAndStatusOrderByCreatedAtAsc(userId, status);
        }
        return ticketForwardRepository.findByToUserIdOrderByCreatedAtDesc(userId, 
            org.springframework.data.domain.Pageable.unpaged()).getContent();
    }

    // ==================== 批量操作功能 ====================

    /**
     * 创建批量操作
     */
    public BatchOperation createBatchOperation(String operationType, String operationName, 
                                             List<Long> ticketIds, Long operatorId, 
                                             Map<String, Object> operationData) {
        try {
            Optional<User> operatorOpt = userRepository.findById(operatorId);
            if (operatorOpt.isEmpty()) {
                throw new RuntimeException("操作者不存在");
            }
            
            BatchOperation operation = BatchOperation.builder()
                    .operationType(operationType)
                    .operationName(operationName)
                    .ticketIds(objectMapper.writeValueAsString(ticketIds))
                    .ticketCount(ticketIds.size())
                    .operator(operatorOpt.get())
                    .operationData(objectMapper.writeValueAsString(operationData))
                    .build();
            
            return batchOperationRepository.save(operation);
        } catch (Exception e) {
            throw new RuntimeException("创建批量操作失败: " + e.getMessage(), e);
        }
    }

    /**
     * 执行批量操作
     */
    public BatchOperation executeBatchOperation(Long operationId) {
        Optional<BatchOperation> operationOpt = batchOperationRepository.findById(operationId);
        if (operationOpt.isEmpty()) {
            throw new RuntimeException("批量操作不存在");
        }
        
        BatchOperation operation = operationOpt.get();
        operation.setStatus("PROCESSING");
        operation.setStartedAt(Instant.now());
        batchOperationRepository.save(operation);
        
        try {
            List<Long> ticketIds = objectMapper.readValue(operation.getTicketIds(), 
                new TypeReference<List<Long>>() {});
            Map<String, Object> operationData = objectMapper.readValue(operation.getOperationData(), 
                new TypeReference<Map<String, Object>>() {});
            
            int successCount = 0;
            int failureCount = 0;
            StringBuilder errorMessages = new StringBuilder();
            
            for (Long ticketId : ticketIds) {
                try {
                    executeSingleOperation(operation.getOperationType(), ticketId, operationData);
                    successCount++;
                } catch (Exception e) {
                    failureCount++;
                    errorMessages.append("工单ID ").append(ticketId).append(": ").append(e.getMessage()).append("; ");
                }
            }
            
            operation.setStatus("COMPLETED");
            operation.setSuccessCount(successCount);
            operation.setFailureCount(failureCount);
            operation.setErrorMessage(errorMessages.length() > 0 ? errorMessages.toString() : null);
            
        } catch (Exception e) {
            operation.setStatus("FAILED");
            operation.setErrorMessage(e.getMessage());
        }
        
        operation.setCompletedAt(Instant.now());
        return batchOperationRepository.save(operation);
    }

    /**
     * 执行单个操作
     */
    private void executeSingleOperation(String operationType, Long ticketId, Map<String, Object> operationData) {
        Optional<Ticket> ticketOpt = ticketRepository.findById(ticketId);
        if (ticketOpt.isEmpty()) {
            throw new RuntimeException("工单不存在");
        }
        
        Ticket ticket = ticketOpt.get();
        
        switch (operationType) {
            case "UPDATE_STATUS":
                String newStatus = (String) operationData.get("status");
                ticket.setStatus(com.example.backend.domain.enums.TicketStatus.valueOf(newStatus));
                break;
            case "ASSIGN":
                Long assigneeId = Long.valueOf(operationData.get("assigneeId").toString());
                Optional<User> assigneeOpt = userRepository.findById(assigneeId);
                if (assigneeOpt.isPresent()) {
                    ticket.setAssignedTo(assigneeOpt.get());
                }
                break;
            case "UPDATE_PRIORITY":
                String newPriority = (String) operationData.get("priority");
                ticket.setPriority(com.example.backend.domain.enums.TicketPriority.valueOf(newPriority));
                break;
            default:
                throw new RuntimeException("不支持的操作类型: " + operationType);
        }
        
        ticketRepository.save(ticket);
    }

    /**
     * 获取用户的批量操作记录
     */
    public List<BatchOperation> getUserBatchOperations(Long userId) {
        return batchOperationRepository.findByOperatorIdOrderByCreatedAtDesc(userId, 
            org.springframework.data.domain.Pageable.unpaged()).getContent();
    }

    /**
     * 获取批量操作统计
     */
    public Map<String, Object> getBatchOperationStats(Long userId) {
        Long totalOperations = batchOperationRepository.countByOperatorId(userId);
        Long successfulOperations = batchOperationRepository.countSuccessfulOperationsByOperatorId(userId);
        
        return Map.of(
            "totalOperations", totalOperations,
            "successfulOperations", successfulOperations,
            "successRate", totalOperations > 0 ? (double) successfulOperations / totalOperations * 100 : 0
        );
    }
}
